﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace LilTmSim
{
	/// <summary>
	/// Interaction logic for RenameControl.xaml
	/// </summary>
	public partial class RenameControl : UserControl, IRenameValidator
	{
		public static readonly RoutedEvent DeleteClickedEvent = EventManager.RegisterRoutedEvent("DeleteClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RenameControl));
		public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(RenameControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
		public static readonly DependencyProperty ModifyingProperty = DependencyProperty.Register("Modifying", typeof(bool), typeof(RenameControl), new UIPropertyMetadata(false));
		public static readonly DependencyProperty ErrorMessageProperty = DependencyProperty.Register("ErrorMessage", typeof(string), typeof(RenameControl), new UIPropertyMetadata(""));

		public event RoutedEventHandler DeleteClicked
		{
			add { AddHandler(DeleteClickedEvent, value); }
			remove { RemoveHandler(DeleteClickedEvent, value); }
		}
		public string Text
		{
			get { return (string)GetValue(TextProperty); }
			set { SetValue(TextProperty, value); }
		}
		public bool Modifying
		{
			get { return (bool)GetValue(ModifyingProperty); }
			set { SetValue(ModifyingProperty, value); }
		}
		public string ErrorMessage
		{
			get { return (string)GetValue(ErrorMessageProperty); }
			set { SetValue(ErrorMessageProperty, value); }
		}

		public List<IRenameValidator> Validators { get; set; }

		public RenameControl()
		{
			Validators = new List<IRenameValidator>();
			Initialized += delegate
			{
				TextEdit.LostKeyboardFocus += delegate { if(Modifying) SaveEdit(); };
			};
			AddHandler(UserControl.MouseLeftButtonDownEvent, new MouseButtonEventHandler(RenameControl_MouseLeftButtonDown));
			InitializeComponent();
		}

		private void RenameControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			if (Keyboard.Modifiers == ModifierKeys.Shift)
			{
				if (sender == this)
					StartEdit();
				e.Handled = true;
			}
		}

		private void StartEdit()
		{
			Modifying = !Modifying;
			ErrorMessage = "";
			TextEdit.SelectAll();
			TextEdit.Focus();
		}

		private void CancelEdit()
		{
			Modifying = !Modifying;
			ErrorMessage = "";
			BindingOperations.GetBindingExpression(TextEdit, TextBox.TextProperty).UpdateTarget();
		}

		private void SaveEdit()
		{
			Modifying = !Modifying;
			try
			{
				if (Validate(TextEdit.Text))
				{
					BindingOperations.GetBindingExpression(TextEdit, TextBox.TextProperty).UpdateSource();
					BindingOperations.GetBindingExpression(this, TextProperty).UpdateTarget();
				}
				ErrorMessage = "";
			}
			catch (Exception exc)
			{
				StartEdit();
				ErrorMessage = exc.Message;
			}
		}

		private void Delete()
		{
			Modifying = !Modifying;
			RaiseEvent(new RoutedEventArgs(DeleteClickedEvent, this));
		}

		private void Button_EditSave_Click(object sender, RoutedEventArgs e)
		{
			if (Modifying)
				SaveEdit();
			else
				StartEdit();
		}

		private void Button_DeleteCancel_Click(object sender, RoutedEventArgs e)
		{
			if (Modifying)
				CancelEdit();
			else
				Delete();
		}

		private void TextEdit_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.Key == Key.D && Keyboard.Modifiers == ModifierKeys.Control)
			{
				int start = TextEdit.SelectionStart;
				TextEdit.Text = TextEdit.Text.Remove(start, TextEdit.SelectionLength);
				TextEdit.Text = TextEdit.Text.Insert(start, TuringTab.DELTA);
				TextEdit.Select(start + 1, 0);
			}
			else if (e.Key == Key.Escape)
			{
				CancelEdit();
			}
			else if (e.Key == Key.Enter || e.Key == Key.Return)
			{
				Focusable = true;
				Focus();
			}
		}

		#region IRenameValidator Members

		public bool Validate(string text)
		{
			return Validators.Count == 0 || Validators.All(validator => validator.Validate(text));
		}

		#endregion
	}

	public interface IRenameValidator
	{
		bool Validate(string text);
	}
}
